/*!
\copyright  Copyright (c) 2024-2025 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file       
\brief      Fast Pair common state handling
*/

#include "fast_pair_common_state_handling.h"

static bool fastpair_CommonStateHandlingAclConnect(fast_pair_state_event_connect_args_t* args)
{
    bool status = FALSE;
    fastPairTaskData *theFastPair = fastPair_GetTaskData();
    DEBUG_LOG("fastpair_CommonStateHandlingAclConnect");
    if (args->connect_ind->tpaddr.transport == TRANSPORT_BLE_ACL && !BtDevice_LeDeviceIsPeer(&(args->connect_ind->tpaddr)))
    {
        /* Determine the local address used to create the new ACL. */
        ConnectionSmBleReadRandomAddressTaskReq(&theFastPair->task, ble_read_random_address_local, &(args->connect_ind->tpaddr));
        status = TRUE;
    }
    return status;
}

static bool fastpair_CommonStateHandlingRpaEvent(fast_pair_state_event_rpa_addr_args_t* args)
{
    bool status = FALSE;

#ifdef USE_SYNERGY
    fastPairTaskData *theFastPair = fastPair_GetTaskData();
    uint16_t result = args->rpa_cfm->resultCode;;
    uint8_t flag = args->rpa_cfm->flag;
    tp_bdaddr peer_tp_addr = { .transport = TRANSPORT_BLE_ACL };
    bdaddr own_bd_addr = { 0 };

    DEBUG_LOG("fastpair_CommonStateHandlingRpaEvent");
    if ((result == success) && (flag == ble_read_random_address_local))
    {
        BdaddrConvertBluestackToVm(&own_bd_addr, &args->rpa_cfm->rpa);
        BdaddrConvertTypedBluestackToVm(&peer_tp_addr.taddr, &args->rpa_cfm->idAddress);

        /* Ensure the connection still exists */
        if (!ConManagerIsTpConnected(&peer_tp_addr))
        {
            DEBUG_LOG("fastpair_CommonStateHandlingRpaEvent, already disconnected, lap=%06x", peer_tp_addr.taddr.addr.lap);
            return TRUE;
        }
        for (uint8 index = 0; index < MAX_BLE_CONNECTIONS; index++)
        {
            PanicNotZero(BdaddrIsSame(&theFastPair->peer_bd_addr[index], &peer_tp_addr.taddr.addr));
            /* Store own and peer BD_ADDRs into a free entry.
             * These are the BD_ADDRs used to create the current connection, which may be Random or Public. */
            if (BdaddrIsZero(&theFastPair->peer_bd_addr[index]))
            {
                DEBUG_LOG("fastpair_CommonStateHandlingRpaEvent, caching own and peer BD_ADDRs, index=%u", index);
                theFastPair->peer_bd_addr[index] = peer_tp_addr.taddr.addr;
                theFastPair->own_random_address[index] = own_bd_addr;
                DEBUG_LOG("\tPeer BD_ADDR: %04x:%02x:%06lx", theFastPair->peer_bd_addr[index].nap,
                                                             theFastPair->peer_bd_addr[index].uap,
                                                             theFastPair->peer_bd_addr[index].lap);
                DEBUG_LOG("\tOwn BD_ADDR: %04x:%02x:%06lx", theFastPair->own_random_address[index].nap,
                                                            theFastPair->own_random_address[index].uap,
                                                            theFastPair->own_random_address[index].lap);
                break;
            }
        }
        status = TRUE;
    }
#endif
    return status;
}

static bool fastpair_CommonStateHandlingAclDisconnect(fast_pair_state_event_disconnect_args_t* args)
{
    bool status = FALSE;
    uint8 index;
    fastPairTaskData *theFastPair;
    DEBUG_LOG("fastpair_CommonStateHandlingAclDisconnect");
    theFastPair = fastPair_GetTaskData();
    if(args->disconnect_ind->tpaddr.transport == TRANSPORT_BLE_ACL)
    {
        for(index = 0; index < MAX_BLE_CONNECTIONS; index++)
        {
            if(BdaddrIsSame(&theFastPair->peer_bd_addr[index], &args->disconnect_ind->tpaddr.taddr.addr))
            {
                DEBUG_LOG("fastpair_CommonStateHandlingAclDisconnect, clearing cached BD_ADDRs, index=%u", index);
                memset(&theFastPair->peer_bd_addr[index], 0x0, sizeof(bdaddr));
                memset(&theFastPair->own_random_address[index], 0x0, sizeof(bdaddr));
            }
        }
        if (BdaddrTpIsSame(&(theFastPair->session_data.session_addr), &(args->disconnect_ind->tpaddr)))
        {
            /* A valid session address implies there's an ongoing Fast Pairing.
             * Consider it ended (success or not), if the Seeker gets disconnected. */
            DEBUG_LOG("fastpair_CommonStateHandlingAclDisconnect, ending FP session");
            fastPair_SetState(theFastPair, FAST_PAIR_STATE_IDLE);
        }
        status = TRUE;
    }
    return status;
}

bool FastPair_CommonStateHandler(fast_pair_state_event_t event)
{
    fastPairTaskData *theFastPair = fastPair_GetTaskData();
    bool status = FALSE;
    DEBUG_LOG_VERBOSE("FastPair_CommonStateHandler, enum:fastPairState:%u, enum:fast_pair_state_event_id:%u", theFastPair->state, event.id);
    /* Only args-ful events are handled from this point onwards. */
    if (event.args == NULL)
    {
        return status;
    }
    switch (event.id)
    {
        case fast_pair_state_event_connect:
        {
            status = fastpair_CommonStateHandlingAclConnect((fast_pair_state_event_connect_args_t *)event.args);
        }
        break;
        case fast_pair_state_event_disconnect:
        {
            status = fastpair_CommonStateHandlingAclDisconnect((fast_pair_state_event_disconnect_args_t *)event.args);
        }
        break;
        case fast_pair_state_event_rpa_addr:
        {
            status = fastpair_CommonStateHandlingRpaEvent((fast_pair_state_event_rpa_addr_args_t *)event.args);
        }
        break;
        default:
            break;
    }
    return status;
}